#pragma once
#include <iostream>
#include <string>
#include "LinePtr.h"
#include "Obstacles.h"
#include "CPoint.h"
#include<ctime>

using namespace std;

// 算法部分============================================================================
class Router{
public:		//寻路结果相关的数据
	std::vector<int> m_path_tree;				//路径搜索树(树根，起点)
	std::vector<int> m_path;					//路径搜索树(树顶，终点)
	std::vector<std::vector<LinePtr>> m_tree_lines;	//搜索树连线
	std::map<NodePoint*, CPoint> m_cpts;			//所有角点
	std::vector<Node> m_nodes;						//所有节点
	std::vector<Obstacles> m_obsArr;				//禁布区集合

	bool do_optimize_level = true;		// 执行节点优化，默认执行
	bool do_post_processing = true;		// 执行后处理，默认执行
	int m_obs_pt_sum = 0;

private:
	std::vector<std::vector<NodePoint>>* m_ptArr;		//地图点数组
	std::vector<std::pair<NodePoint*, NodePoint*>> m_Pins;	//Pin脚数组（起点，终点）
	char obsSymbol = '#';
	char accessSymbol = 'o';
	int xSize;
	int ySize;
	std::vector<NodePoint> directions = { NodePoint(0, 1), NodePoint(1, 0), NodePoint(0, -1), NodePoint(-1, 0) };
	std::vector<NodePoint> four_corners = { NodePoint(1, 1), NodePoint(1, -1), NodePoint(-1, 1), NodePoint(-1, -1) };
	//int optimize_level = 2;		// 优化向前迭代的步数,最小设为1


public:
	Router(std::vector<std::vector<NodePoint>>& ptArr, std::vector<std::pair<NodePoint, NodePoint>>& PinsName) {
		this->m_ptArr = &ptArr;
		xSize = ptArr.size();
		ySize = ptArr[0].size();
		for (auto pt_pair : PinsName) {
			NodePoint* pt1 = &(*m_ptArr)[pt_pair.first.x][pt_pair.first.y];
			NodePoint* pt2 = &(*m_ptArr)[pt_pair.second.x][pt_pair.second.y];
			this->m_Pins.emplace_back(make_pair(pt1, pt2));
		}
	}
	~Router() {
		;
	}
	int set_tree_lines(int root_n);

public:

	void obs_init();				// 禁布区初始化
	void main_router();				// 寻路模块，内部调用路径优化小模块


private:
	// 常用函数
	bool is_inside(int x, int y) const;
	// 禁布区预处理模块
	void add_new_obstacle(NodePoint& pt, int& obsSum);
	bool set_new_cpt(int x, int y, NodePoint& ex_direc);	//给定坐标，生成一个新角点对象
	NodePoint* next_step(NodePoint* step_point, NodePoint* scope_point, char target_symbol);
	NodePoint* old_red_pt = nullptr;
	NodePoint* old_black_pt = nullptr;
	NodePoint out_red_pt = NodePoint(-2, -2);
	NodePoint out_old_red_pt = NodePoint(-2, -2);

	//寻路模块
	bool path_finding(NodePoint* pt1, NodePoint* pt2);
	void set_obs_and_access(NodePoint* pt1, NodePoint* pt2, char symbol);
	bool node_extend(int node1_n, int node2_n);
	bool add_neibor_to_node(int node1_n, NodePoint* ptr);
	bool add_cpt_to_node(int node1_n, int obsIndex);
	int get_next_obs(NodePoint& pt1, NodePoint& pt2);
	std::vector<int> get_all_next_obs(NodePoint& pt1, NodePoint& pt2);		//方案2独有
	NodePoint* m_mid_node_ptr = nullptr;	// 寻一条路径过程中的数据
	multimap<double, int> leaf_nodes;		// 可选择的叶节点，以F为键值的小根堆，寻一条路径过程中的数据
	std::vector<int> m_pass_obss;
	bool set_child_and_value(int parent_n, int child_n, bool ignoreG = false);
	int getNewNode(NodePoint& pt, int obsIndex = -1);
	void finding_data_clear(int root);
	int free_ocupid_pts(int root_n);

	//节点优化模块
	int node_optimize(int node_n, int end_node_index = -1);		//从节点node_n开始回溯和优化，返回最靠近根部的被修改的节点
	int get_n_parent(int node_n, int n);
	bool insert_node(int node1_n, int node2_n, NodePoint* ptr);					// 子节点，父节点，新节点
	bool insert_node(int node1_n, int node2_n, std::vector<NodePoint*> ptrs);	// 子节点，父节点，多个新节点
	vector<NodePoint*> get_mid_node(NodePoint& pt1, NodePoint& pt2);

	//后处理模块
	bool main_post_processing(int node_n);	// 后处理模块
	bool line_post_process(int node1_n, int node2_n, NodePoint* mid_pt, std::vector<int>& pass_obss);
	NodePoint* get_mid_pt(int node1_pre, int node1_n, int node2_n, std::vector<int>& pass_obss);

};